<?php
namespace Util;
Class SfApi
{
    private $url;

    private $header;

    private $appid;

    private $appkey;

    private $access_token;

    private $refresh_token;

    public function __construct()
    {
        $this->url = 'https://open-sbox.sf-express.com/';
        $this->appid = '00048730';
        $this->appkey = '3A7E1F0C8382981EBBBC017F96DFFE46';
        $this->header = array(
            'Content-Type: application/json'
        );
    }

    //获取token
    public function getAccessToken(){
        $rs = array();
        //检查是否存在token
        $redis_instance = \Util\Redis::getInstance();
        $access_token = $redis_instance->get('SF_ACCESS_TOKEN');
        $refresh_token = $redis_instance->get('SF_REFRESH_TOKEN');

        //如果没有,先查询，再申请token
        if(!$access_token || !$refresh_token){
            $returnData = $this->queryToken();
            if(!$returnData){
                $returnData = $this->createToken();
            }
            if($returnData){
                $this->access_token = $rs['accessToken'] = $returnData['accessToken'];
                $this->refresh_token = $rs['refreshToken'] = $returnData['refreshToken'];
            }
        }else{
            $this->access_token = $rs['accessToken'] = $access_token;
            $this->refresh_token = $rs['refreshToken'] = $refresh_token;
        }

        return $rs;
    }

    //查询AccessToken
    private function queryToken(){
        $url = 'public/v1.0/security/access_token/query/sf_appid/'.$this->appid.'/sf_appkey/'.$this->appkey;
        $data = array(
            'head' => array(
                'transType' => '300',
                'transMessageId' => date('YmdHis').rand(1000,9999)
            ),
            'body' => array()
        );
        $postData = json_encode($data,JSON_FORCE_OBJECT);
        $responseData = $this->exec('POST', $url, $postData);
        if($responseData && isset($responseData['head']['code']) && $responseData['head']['code'] == 'EX_CODE_OPENAPI_0200'){
            $redis_instance = \Util\Redis::getInstance();
            $redis_instance->set('SF_ACCESS_TOKEN',$responseData['body']['accessToken']);
            $redis_instance->set('SF_REFRESH_TOKEN',$responseData['body']['refreshToken']);

            $this->access_token = $responseData['body']['accessToken'];
            $this->refresh_token = $responseData['body']['refreshToken'];

            return $responseData['body'];
        }else{
            return false;
        }
    }

    //刷新AccessToken
    private function refreshToken($token,$fresh_token){
        $url = 'public/v1.0/security/refresh_token/access_token/'.$token.'/refresh_token/'.$fresh_token.'/sf_appid/'.$this->appid.'/sf_appkey/'.$this->appkey;
        $data = array(
            'head' => array(
                'transType' => '302',
                'transMessageId' => date('YmdHis').rand(1000,9999)
            ),
            'body' => array()
        );
        $postData = json_encode($data,JSON_FORCE_OBJECT);
        $responseData = $this->exec('POST', $url, $postData);
        if($responseData && isset($responseData['head']['code']) && $responseData['head']['code'] == 'EX_CODE_OPENAPI_0200'){
            $redis_instance = \Util\Redis::getInstance();
            $redis_instance->set('SF_ACCESS_TOKEN',$responseData['body']['accessToken']);
            $redis_instance->set('SF_REFRESH_TOKEN',$responseData['body']['refreshToken']);

            $this->access_token = $responseData['body']['accessToken'];
            $this->refresh_token = $responseData['body']['refreshToken'];

            return $responseData['body'];
        }else{
            return false;
        }
    }

    //申请accessToken
    private function createToken(){
        $url = 'public/v1.0/security/access_token/sf_appid/'.$this->appid.'/sf_appkey/'.$this->appkey;
        $data = array(
            'head' => array(
                'transType' => '301',
                'transMessageId' => date('YmdHis').rand(1000,9999)
            ),
            'body' => array()
        );
        $postData = json_encode($data,JSON_FORCE_OBJECT);
        $responseData = $this->exec('POST', $url, $postData);
        if($responseData && isset($responseData['head']['code']) && $responseData['head']['code'] == 'EX_CODE_OPENAPI_0200'){
            $redis_instance = \Util\Redis::getInstance();
            $redis_instance->set('SF_ACCESS_TOKEN',$responseData['body']['accessToken']);
            $redis_instance->set('SF_REFRESH_TOKEN',$responseData['body']['refreshToken']);

            $this->access_token = $responseData['body']['accessToken'];
            $this->refresh_token = $responseData['body']['refreshToken'];

            return $responseData['body'];
        }else{
            return false;
        }
    }

    //快速下单
    public function createOrder($item){
        $item['consigneeInfo']['address'] = '未知';
        $url = 'rest/v1.0/order/access_token/'.$this->access_token.'/sf_appid/'.$this->appid.'/sf_appkey/'.$this->appkey;
        $data = array(
            'head' => array(
                'transType' => '200',
                'transMessageId' => date('YmdHis').rand(1000,9999)
            ),
            'body' => $item
        );
        $postData = json_encode($data);
        $responseData = $this->exec('POST', $url, $postData);
        if($responseData && isset($responseData['head']['code']) && $responseData['head']['code'] == 'EX_CODE_OPENAPI_0200'){
            return $responseData['body'];
        }elseif ($responseData && isset($responseData['head']['code']) && $responseData['head']['code'] == 'EX_CODE_OPENAPI_0105'){
            //$res = $this->queryToken();
            $re = $this->refreshToken($this->access_token, $this->refresh_token);
            if(!$re){
                $this->createToken();
            }
            return $this->createOrder($item);
        }elseif ($responseData && isset($responseData['head']['code']) && $responseData['head']['code'] == 'EX_CODE_OPENAPI_0106'){
            $re = $this->createToken();
            if($re){
                return $this->createOrder($item);
            }else{
                return false;
            }
        }elseif ($responseData && isset($responseData['head']['code']) && $responseData['head']['code'] == 'EX_CODE_OPENAPI_0103'){
            $re = $this->createToken();
            if($re){
                return $this->createOrder($item);
            }else{
                return false;
            }
        }else{
            return false;
        }
    }

    private function exec($method, $url, $obj = array())
    {

        $curl = curl_init();

        switch ($method) {
            case 'GET':
                if (strrpos($url, "?") === FALSE) {
                    $url .= '?' . http_build_query($obj);
                }
                break;
            case 'POST':
                curl_setopt($curl, CURLOPT_POST, TRUE);
                curl_setopt($curl, CURLOPT_POSTFIELDS, $obj);
                break;
            case 'PUT':
                curl_setopt($curl, CURLOPT_CUSTOMREQUEST, strtoupper($method)); // method
                curl_setopt($curl, CURLOPT_POSTFIELDS, $obj);
                break;
            case 'DELETE':
            default:
                curl_setopt($curl, CURLOPT_CUSTOMREQUEST, strtoupper($method)); // method
                curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($obj)); // body
        }

        curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($curl, CURLOPT_HTTPHEADER, $this->header);
        curl_setopt($curl, CURLOPT_URL, $this->url . $url);
        curl_setopt($curl, CURLOPT_HEADER, TRUE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);

        // Exec
        $response = curl_exec($curl);
        $info = curl_getinfo($curl);
        curl_close($curl);

        // Data
        $body = substr($response, $info['header_size']);
		
        return json_decode($body, true);
    }
}